package com.middlegroup.payadmin.config.shiro;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class ShiroRedisCache<K,V> implements Cache<K,V> {

    private long expire = 30 * 60 * 1000;
    private String keyPrefix = "shiro-session:";
    private RedisTemplate<K,V> redisTemplate;

    public ShiroRedisCache(long expire, String keyPrefix, RedisTemplate<K,V> redisTemplate) {
        this.expire = expire;
        this.keyPrefix = keyPrefix;
        this.redisTemplate = redisTemplate;
    }


    @Override
    public V get(K k) throws CacheException {
        final K sessionKey = getSessionKey(k);
        redisTemplate.boundValueOps(sessionKey).expire(expire, TimeUnit.MILLISECONDS);
        return redisTemplate.boundValueOps(sessionKey).get();
    }

    @Override
    public V put(K sessionId, V session) throws CacheException {
        final K sessionKey = getSessionKey(sessionId);
        V old = get(sessionKey);
        redisTemplate.boundValueOps(sessionKey).set(session);
        return old;
    }

    @Override
    public V remove(K sessionId) throws CacheException {
        final K sessionKey = getSessionKey(sessionId);
        V old = get(sessionKey);
        redisTemplate.delete(sessionKey);
        return old;
    }

    @Override
    public void clear() throws CacheException {
        redisTemplate.delete(keys());
    }

    @Override
    public int size() {
        return keys().size();
    }

    @Override
    public Set<K> keys() {
        return redisTemplate.keys(getSessionKey((K) "*"));
    }
    @Override
    public Collection<V> values() {
        Set<K> set = keys();
        List<V> list = new ArrayList<>();
        for (K sessionId : set) {
            list.add(get(sessionId));
        }
        return list;
    }

    private K getSessionKey(K sessionId) {
        return (K) (keyPrefix + sessionId);
    }
}